/******************************************************************************
 * FileName:    gwin_main_task.c
 * Desc:        main
 *
 *
 * Author:      Lin
 * Notes:
 *
 ******************************************************************************/

/*-------------------------- Includes ---------------------------------------*/
#include "gwin_global_config.h"
#include "gwin_protocol_task.h"
#include "gwin_spec.h"
#include "gwin_main_task.h"

#include "gwin_dev_info_pkt.h"
#include "miio_user_api.h"

/*-------------------------- Macro Definitions ------------------------------*/
#define LOCAL_DEBUG_EN                      ( 0 )
#if LOCAL_DEBUG_EN
#define GWIN_DEBUG(...)                     USER_DEBUG(__VA_ARGS__)
#else
#define GWIN_DEBUG(...)
#endif


#define GWIN_MAIN_TASK_PRIORITY             ( 3 )       // 任务优先级，值越大优先级越高       保证主任务优先级最高！！！保证低优先级任务调用！！！否则 gwin_main_cfg_get 会有问题！！！
#define GWIN_MAIN_TASK_STACK_SIZE           ( 2048 )    // 任务栈
#define GWIN_MAIN_TASK_QUEUE_MAX_NUM        ( 32 )      // 消息队列


/*-------------------------- Type Declarations ------------------------------*/

/*-------------------------- Global Variables -------------------------------*/
/**
 * @brief 系统参数
 */
system_param_t system_param = { 0 };


/*-------------------------- Local Variables --------------------------------*/
static void *gwin_main_task_handle; //!< APP Task handle
static void *gwin_main_queue_handle = NULL;

_os_timer_declaration(reset_all_force);
_os_timer_declaration(one_second);
_os_timer_declaration(pwr_on_wait_loop);
_os_timer_declaration(low_pwr_enter);

// 创建广播信息回复定时器
_os_timer_declaration(adv_dev_info_pkt);

/*-------------------------- Functions Declarations -------------------------*/
static void gwin_main_task(void *arg);
static void gwin_main_reset_all_force_callback(void *arg);
static void gwin_main_pwr_on_wait_loop_callback(void *arg);
static void gwin_main_low_pwr_enter_callback(void *arg);
static void gwin_main_one_second_callback(void *arg);
static void gwin_main_adv_dev_info_pkt_callback(void *arg);

static void gwin_main_task_timer_msg_handle(gwin_main_task_msg_t *msg);
static void gwin_main_task_cfg_msg_handle(gwin_main_task_msg_t *msg);
static void gwin_main_task_extern_action_msg_handle(gwin_main_task_msg_t *msg);

static void gwin_main_power_on(void);
static void gwin_main_hold_wakeup(uint8_t power_on);
static void gwin_main_set_adv_dev_info_pkt(void);
static void gwin_main_func_start(void);
//static void gwin_main_system_reboot(void);
static void _gwin_main_system_reboot(void);
static void gwin_main_network_reset(void);
static void _gwin_main_network_reset(void);
static void gwin_main_factory_test(void);
static void _gwin_main_factory_test(void);


/*-------------------------- Functions Definitions --------------------------*/
/**
 * @brief 设置参数 修改
 */
void gwin_main_cfg_set(uint32_t cfg_index, uint32_t value)
{
    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_CFG;
    msg.subtype = cfg_index;
    msg.action_type = MAIN_TASK_MSG_CFG_ACT_TYPE_SET;
    msg.cfg_value = value;
    gwin_send_msg_to_main_task(&msg);
}

/**
 * @brief 设置参数 读取
 *          保证主任务优先级最高！！！保证低优先级任务调用！！！否则 gwin_main_cfg_get 会有问题！！！
 */
void gwin_main_cfg_get(uint32_t cfg_index, uint32_t value_addr)
{
    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_CFG;
    msg.subtype = cfg_index;
    msg.action_type = MAIN_TASK_MSG_CFG_ACT_TYPE_GET;
    msg.cfg_value = value_addr;
    gwin_send_msg_to_main_task(&msg);
}

/**
 * @brief 外部动作
 */
void gwin_main_extern_action(uint8_t action)
{
    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_EX_ACT;
    msg.subtype = action;
    gwin_send_msg_to_main_task(&msg);
}

/**
 * @brief 外部动作
 */
void gwin_main_extern_action_with_param(uint8_t action, uint32_t param)
{
    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_EX_ACT;
    msg.subtype = action;
    msg.ext_param = param;
    gwin_send_msg_to_main_task(&msg);
}


/**
 * @brief 更新系统状态
 */
void gwin_main_sys_state_update(void)
{
    if (system_param.factory_test)
    {
        system_param.sys_state = SYS_STATE_FACTORY_TEST;
    }
    else if (system_param.gatt_state)
    {
        system_param.sys_state = SYS_STATE_CONNECT;
    }
    else if (system_param.low_pwr_ctrl_second == 0)
    {
        system_param.sys_state = SYS_STATE_LOW_PWR;
    }
    else
    {
        if (system_param.network_provisioned)
        {
            system_param.sys_state = SYS_STATE_DISCONNECT;
        }
        else
        {
            system_param.sys_state = SYS_STATE_WAIT_PAIR;
        }
    }

    if (system_param.sys_state_extern != system_param.sys_state)
    {
        system_param.sys_state_extern = system_param.sys_state;
        gwin_protocol_data_send_mcu(GWIN_PROT_CMD_SYS_STATE);
    }
}
/**
 * @brief 更新系统状态 瞬态
 */
void gwin_main_sys_state_update_transient(uint8_t sys_state)
{
    gwin_protocol_data_send_mcu(GWIN_PROT_CMD_SYS_STATE | (sys_state << 8));
}


/**
 * @brief 唤醒
 */
void gwin_main_extern_wakeup(uint8_t pin)
{
    gwin_main_extern_action_with_param(MAIN_TASK_MSG_EX_ACT_SUBTYPE_WAKEUP, pin);
}

/**
 * @brief 唤醒
 */
static void gwin_main_hold_wakeup(uint8_t power_on)
{
    if (!power_on         // 上电不能马上调度ble协议栈接口，还没初始化
            && !system_param.gatt_state)
    {
        gwin_main_ble_set_adv_interval(1, 0);
    }

    gwin_low_pwr_set(0);
    system_param.low_pwr_ctrl_second = LOW_PWR_TIME_SECOND;
    if (_os_timer_is_active(low_pwr_enter))
    {
        _os_timer_stop(low_pwr_enter, 0);
    }
}

/**
 * @brief 设置广播间隔
 */
void gwin_main_ble_set_adv_interval(uint8_t quick, uint8_t force)
{
    uint16_t ble_adv_interval;
    if (quick)
    {
        ble_adv_interval = BLE_ADV_INTERVAL_QUICK;
    }
    else
    {
        ble_adv_interval = BLE_ADV_INTERVAL;
    }
    if (system_param.ble_adv_interval != ble_adv_interval || force)
    {
        system_param.ble_adv_interval = ble_adv_interval;
        miio_ble_user_adv_start(system_param.ble_adv_interval);
    }
}

/**
 * @brief 设置广播
 */
void gwin_main_ble_set_cfg_info_pkt(void)
{
    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_CFG;
    msg.subtype = MAIN_TASK_MSG_CFG_SUBTYPE_SET_INFO_PKT;
    msg.action_type = MAIN_TASK_MSG_CFG_ACT_TYPE_SET;
    gwin_send_msg_to_main_task(&msg);
}

/**
 * @brief 上电初始化
 */
static void gwin_main_power_on(void)
{
    SYSTEM_DEBUG("");
    SYSTEM_DEBUG("--- SYSTEM POWER ON ---");
    SYSTEM_DEBUG("--- build time : \t\t%s %s", __DATE__, __TIME__);
    SYSTEM_DEBUG("--- firmware : \t\t%s", GWIN_FW_NAME_TOTAL);
    SYSTEM_DEBUG("--- model : \t\t%s", system_param.product.model);
    SYSTEM_DEBUG("--- pid : \t\t\t%d", system_param.product.pid);
    SYSTEM_DEBUG("--- version : \t\t%s", system_param.product.version);
    SYSTEM_DEBUG("--- miot_security_siid : \t%d", system_param.product.miot_security_siid);

    // 更新系统状态
    gwin_main_sys_state_update_transient(SYS_STATE_START);
//    gwin_main_sys_state_update();

    _os_timer_start(one_second, 0);
    _os_timer_start(pwr_on_wait_loop, 0);
    gwin_protocol_data_send_mcu(GWIN_PROT_CMD_MODEL_PID_RSQ);

    // 属性补发机制
    for (uint8_t i = 0; i < system_param.spec.len; i++)
    {
        if (system_param.spec.data[i].change)
        {
            gwin_save_general_clock(&system_param.system_upload_clock[i]);
        }
    }

    gwin_main_hold_wakeup(1);
    gwin_low_pwr_set_callback(gwin_main_extern_wakeup);
}


/**
 * @brief 发送广播包 设备配对二维码
 */
void gwin_main_set_adv_dev_pair_info_pkt(const uint8_t *qrcode, uint8_t len)
{
    #define ADV_DATA_HEAD           0
    #if ADV_DATA_HEAD
    static const uint8_t adv_data_head[] = { 0x02, 0x01, 0x06 };
    uint8_t adv_data[sizeof(adv_data_head) + sizeof(dev_pair_info_t)];
    memcpy(&adv_data[0], adv_data_head, sizeof(adv_data_head));
    dev_pair_info_t *dev_pair_info_pkt = (dev_pair_info_t *)&adv_data[sizeof(adv_data_head)];
    #else
    uint8_t adv_data[sizeof(dev_pair_info_t)];
    dev_pair_info_t *dev_pair_info_pkt = (dev_pair_info_t *)&adv_data[0];
    #endif
    memset(dev_pair_info_pkt, 0x00, sizeof(dev_pair_info_t));
    dev_pair_info_pkt->ble_adv_len = sizeof(dev_pair_info_t) - 1;
    dev_pair_info_pkt->ble_adv_type = GWIN_GAP_ADTYPE_MANUFACTURER_SPECIFIC;
    dev_pair_info_pkt->company_id = GWIN_COMPANY_ID_DEV_PAIR_INFO;
    dev_pair_info_pkt->pid = HL_SWAP_U16(GWIN_PRODUCT_ID_DEV_PAIR_INFO);
    memcpy(dev_pair_info_pkt->mac_addr, system_param.mac_addr, sizeof(dev_pair_info_pkt->mac_addr));
    dev_pair_info_pkt->product_type = GWIN_PRODUCT_TYPE_DEV_PAIR_INFO;
    len = MIN(sizeof(dev_pair_info_pkt->qrcode), len);
    memcpy(dev_pair_info_pkt->qrcode, qrcode, len);
    gap_set_adv(adv_data, sizeof(adv_data));
}

/**
 * @brief 发送广播包 设备信息数据包
 */
static void gwin_main_set_adv_dev_info_pkt(void)
{
    static const uint8_t adv_data_head[] = { 0x02, 0x01, 0x06 };
    uint8_t adv_data[sizeof(adv_data_head) + sizeof(dev_info_pkt_comm_adv_t)];
    memcpy(&adv_data[0], adv_data_head, sizeof(adv_data_head));
    gwin_main_dev_info_pkt_comm_adv(&adv_data[sizeof(adv_data_head)], sizeof(dev_info_pkt_comm_adv_t),
                            system_param.mac_addr,
                            system_param.product.pid);
    gap_set_adv(adv_data, sizeof(adv_data));
}


/**
 * @brief 开始正式功能
 */
static void gwin_main_func_start(void)
{
    if (!system_param.func_start)
    {
        system_param.func_start = 1;
        gwin_main_sys_state_update();
    }
}

/**
 * @brief 重启
 */
//static void gwin_main_system_reboot(void)
//{
//    GWIN_DEBUG("");
//
//    system_param.reboot = 1;
//    system_param.delay_reboot = DELAY_REBOOT;
//}
/**
 * @brief 重启
 */
static void _gwin_main_system_reboot(void)
{
    GWIN_DEBUG("");

    system_reboot();
}

/**
 * @brief 重新配网
 */
static void gwin_main_network_reset(void)
{
    GWIN_DEBUG("");

    system_param.network_reset = 1;

    // 重置配网，清除所有参数
    gwin_custom_record_reset_all();

    // 重置配网，清除配网标记
    system_param.network_provisioned = 0;
    gwin_custom_record_save(RECORD_ID_NETWORK);

    system_param.delay_network_reset = DELAY_NETWORK_RESET;
}
/**
 * @brief 重新配网
 */
static void _gwin_main_network_reset(void)
{
    GWIN_DEBUG("");

    // 重置配网后搜索绑定报错-17
    extern void mible_record_clear(void);
    mible_record_clear();

    network_restore();
}

/**
 * @brief 工厂测试
 */
static void gwin_main_factory_test(void)
{
    GWIN_DEBUG("");

    system_param.factory_test = 1;
    system_param.delay_factory = 3;     // 太快进工厂测试，会被SDK重置广播包！！！

    // 更新系统状态
    gwin_main_sys_state_update();
}
/**
 * @brief 工厂测试
 */
static void _gwin_main_factory_test(void)
{
    GWIN_DEBUG("");

    gwin_main_set_adv_dev_info_pkt();
}


/**
 * @brief 定时器消息处理
 */
static void gwin_main_task_timer_msg_handle(gwin_main_task_msg_t *msg)
{
    uint16_t subtype = msg->subtype;

    switch(subtype)
    {
        case MAIN_TASK_MSG_TIMER_SUBTYPE_ONE_SECOND:
            {
                system_param.second++;

                // 延时 保存spec
                // LIN MARK 20240402 : MHCWB11S SDK，串口接收有bug，注意频繁写flash，会频繁关闭中断，导出串口rx偏移
                if (system_param.delay_spec_save > 0)
                {
                    system_param.delay_spec_save--;
                    if (system_param.delay_spec_save == 0)
                    {
                        gwin_custom_record_save(RECORD_ID_SPEC);
                    }
                }
                if (system_param.delay_spec_str_save > 0)
                {
                    system_param.delay_spec_str_save--;
                    if (system_param.delay_spec_str_save == 0)
                    {
                        gwin_custom_record_save(RECORD_ID_SPEC_STR);
                    }
                }
                // 延时 重启
                if (system_param.delay_reboot > 0)
                {
                    system_param.delay_reboot--;
                    if (system_param.delay_reboot == 0)
                    {
                        _gwin_main_system_reboot();
                    }
                }
                // 延时 重置网络
                if (system_param.delay_network_reset > 0)
                {
                    system_param.delay_network_reset--;
                    if (system_param.delay_network_reset == 0)
                    {
                        _gwin_main_network_reset();
                    }
                }
                // 延时 厂测
                if (system_param.delay_factory > 0)
                {
                    system_param.delay_factory--;
                    if (system_param.delay_factory == 0)
                    {
                        _gwin_main_factory_test();
                    }
                }

                // 激活配对
                if (system_param.active_pair_time > 0)
                {
                    system_param.active_pair_time--;
                    if (system_param.active_pair_time == 0)
                    {
                        miio_ble_user_adv_init(0);
                    }
                }

                // 校准
//                if (system_param.network_state)
//                {
//                    // 校准，逐一校准，防止上报浪费
//                    if (!system_param.utc_time_valid)
//                    {
//                        if (system_param.second % MESH_REQUEST_INFO_TIME == 0)
//                        {
//                            spec_request_utc_time();
//                        }
//                    }
//                    else if (system_param.timezone == INVALID_I8)
//                    {
//                        spec_request_gmt_offset();
//                    }
//                    else if (system_param.weather == INVALID_U16)
//                    {
//                        spec_request_weather();
//                    }
//                    else
//                    {
//                        if (system_param.second % 3600 == 0)   // 每小时校准
//                        {
//                            spec_request_utc_time();
//                            spec_request_gmt_offset();
//                            spec_request_weather();
//                        }
//                    }
//                }

                // 工厂测试
                // 厂测入口关闭
                if (!system_param.factory_enter_disable && system_param.second >= 5)
                {
                    system_param.factory_enter_disable = 1;
                }

                // 正式开始功能
                if (!system_param.func_start && system_param.second >= 5)
                {
                    gwin_main_func_start();
                }


                // 配网、蓝牙直连初期，系统参数强制延时，马上上报可能死机
                if (system_param.system_upload_force_wait > 0)
                {
                    system_param.system_upload_force_wait--;
                    if (system_param.system_upload_force_wait == 0)
                    {
                        for (uint8_t i = 0; i < system_param.spec.len; i++)
                        {
                            if (system_param.spec.data[i].change)
                            {
                                gwin_save_general_clock(&system_param.system_upload_clock[i]);
                            }
                        }
                    }
                }

                // 查看系统上报参数，上报
                if (system_param.network_state && system_param.network_provisioned)
                {
                    uint8_t upload_success = 1;
                    uint8_t upload_cnt = 0;
                    uint8_t need_save = 0;

                    for (uint8_t i = 0; i < system_param.spec.len; i++)
                    {
                        if ((gwin_get_general_clock_is_start(&system_param.system_upload_clock[i]) && system_param.gatt_state)  // 蓝牙直连，直接发
                                || gwin_pass_general_clock(system_param.system_upload_clock[i], SYS_UPLOAD_TIME * 1000))        // mesh连接，普通属性延时发
                        {
                            if (system_param.spec.data[i].change)
                            {
                                if (upload_success)             // 只要有一个失败，接下来所有参数，本次都不再尝试发送（重点参数请往前移动）
                                {
                                    ++upload_cnt;
                                    upload_success = gwin_spec_property_changed(system_param.spec.data[i].siid, system_param.spec.data[i].piid, system_param.spec.data[i].data_type, system_param.spec.data[i].value);
                                }
                            }
                            else
                            {
                                upload_success = 1;
                            }

                            if (!upload_success)
                            {
                                gwin_save_general_clock(&system_param.system_upload_clock[i]);
                            }
                            else
                            {
                                gwin_clear_general_clock(&system_param.system_upload_clock[i]);
                                system_param.spec.data[i].change = 0;
                                need_save = 1;
                            }

                            // 限制最多一次性上报，因为：一次性上报很多条都是底层接口malloc压栈，占用内存
                            if (upload_cnt >= SYS_UPLOAD_PER_SECOND_CNT_MAX)
                            {
                                break;
                            }

                            // 最后一条参数上报
                            if (i == (system_param.spec.len - 1))
                            {
                                if (!system_param.spec.upload_total)
                                {
                                    system_param.spec.upload_total = 1;
                                    need_save = 1;
                                }
                            }
                        }
                    }

                    // 保存
                    if (need_save)
                    {
                        gwin_custom_record_save(RECORD_ID_SPEC);
                    }
                }

                // 配网超时
                if (!system_param.network_provisioned)
                {
                    if (system_param.network_timeout > 0)
                    {
                        system_param.network_timeout--;
                        GWIN_DEBUG("network_timeout = %d", system_param.network_timeout);

                        if (system_param.network_timeout == 0)
                        {
                            system_param.network_provisioned = 1;
                            gwin_custom_record_save(RECORD_ID_NETWORK);

                            // 更新系统状态
                            gwin_main_sys_state_update();
                        }
                    }
                }

                // 低功耗
                if (system_param.gatt_state
                        || system_param.ota_state
                        || system_param.factory_test
                        || !system_param.func_start
                        || system_param.network_timeout)
                {
                    gwin_main_hold_wakeup(0);
                }
                else
                {
                    if (system_param.low_pwr_ctrl_second > 0)
                    {
                        system_param.low_pwr_ctrl_second--;
                        GWIN_DEBUG("low pwr cnt down = %d", system_param.low_pwr_ctrl_second);
                        if (system_param.low_pwr_ctrl_second == 0)
                        {
                            GWIN_DEBUG("gwin enter low pwr .....");

                            gwin_main_sys_state_update();

                            gwin_main_ble_set_adv_interval(0, 0);
                            _os_timer_start(low_pwr_enter, 0);
                        }
                    }
                }
            }
            break;

        case MAIN_TASK_MSG_TIMER_SUBTYPE_PWR_ON_WAIT_LOOP:
            if (!system_param.func_start)
            {
                gwin_protocol_data_send_mcu(GWIN_PROT_CMD_MODEL_PID_RSQ);
                _os_timer_start(pwr_on_wait_loop, 0);
            }
            break;

        case MAIN_TASK_MSG_TIMER_SUBTYPE_LOW_PWR_ENTER:
            gwin_low_pwr_set(1);
            break;

        case MAIN_TASK_MSG_TIMER_SUBTYPE_RESET_ALL_FORCE:
            {
                // LIN MARK 230726 : 上电不能马上重置网络，所以定时器延时等协议栈初始化，对所有参数重置
                gwin_custom_record_reset_all_force_force();
                network_restore();
            }
            break;

        case MAIN_TASK_MSG_TIMER_SUBTYPE_STOP_INFO_PKT:
            {
                gwin_ble_adv_stop();
            }
            break;

        default:
            GWIN_DEBUG("Error : subtype of timer msg is unknown %d !!!", subtype);
            break;
    }
}

/**
 * @brief 设置消息处理
 */
static void gwin_main_task_cfg_msg_handle(gwin_main_task_msg_t *msg)
{
    uint16_t subtype = msg->subtype;
    uint8_t action_type = msg->action_type;

    // 某些条件不响应外部指令
    uint8_t busy = 0;
    if (system_param.reboot)
    {
        GWIN_DEBUG("reboot!!!");
        busy = 1;
    }
    if (system_param.network_reset)
    {
        GWIN_DEBUG("network reset!!!");
        busy = 1;
    }
    if (system_param.factory_test)
    {
        GWIN_DEBUG("factory test!!!");
        busy = 1;
    }
    if (system_param.ota_state)
    {
        GWIN_DEBUG("ota is running!!!");
        busy = 1;
    }
    if (busy && action_type != MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
    {
        return;
    }

    if (action_type != MAIN_TASK_MSG_CFG_ACT_TYPE_SET
            && action_type != MAIN_TASK_MSG_CFG_ACT_TYPE_GET
            && action_type != MAIN_TASK_MSG_CFG_ACT_TYPE_TOGGLE
            && action_type != MAIN_TASK_MSG_CFG_ACT_TYPE_RESET)
    {
        GWIN_DEBUG("Error : cfg action type none!!!");
        return;
    }
    if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET && msg->cfg_value == 0)           // 获取的时候，传了空指针，会死机
    {
        GWIN_DEBUG("Error : cfg action get %d pointer is null!!!", subtype);
        return;
    }

    GWIN_DEBUG("subtype = %d, action_type = %d, cfg_value = %d", subtype, action_type, msg->cfg_value);

    switch(subtype)
    {
        case MAIN_TASK_MSG_CFG_SUBTYPE_TIME_ZONE:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                int8_t *value_addr = (int8_t *)msg->cfg_value;
                *value_addr = system_param.timezone;
            }
            else
            {
                int8_t cfg_value = (int8_t)msg->cfg_value;
                system_param.timezone = cfg_value;
            }
            break;
        case MAIN_TASK_MSG_CFG_SUBTYPE_UTC_TIME:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                uint32_t *value_addr = (uint32_t *)msg->cfg_value;
                *value_addr = system_get_utc();
            }
            else
            {
                system_param.utc_time_valid = 1;
                uint32_t cfg_value = msg->cfg_value;
                system_set_utc(cfg_value);
            }
            break;
        case MAIN_TASK_MSG_CFG_SUBTYPE_WEATHER:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                uint32_t *value_addr = (uint32_t *)msg->cfg_value;
                *value_addr = system_param.weather;
            }
            else
            {
                uint16_t cfg_value = msg->cfg_value;
                system_param.weather = cfg_value;
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_SYS_STATE:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                uint32_t *value_addr = (uint32_t *)msg->cfg_value;
                *value_addr = system_param.sys_state;
            }
            else
            {

            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_NETWORK:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {

            }
            else
            {
                // 这里不代表已经连上网关！！！！！
                uint8_t cfg_value = msg->cfg_value;
                uint8_t network_provisioned = cfg_value ? 1 : 0;
                system_param.network_state = network_provisioned;
                if (system_param.network_state)
                {
                    system_param.network_timeout = 0;
                }
                if (system_param.network_provisioned != network_provisioned)                // 上电就会发出配网状态，做个锁，防止频繁修改flash
                {
                    system_param.network_provisioned = network_provisioned;
                    gwin_custom_record_save(RECORD_ID_NETWORK);
                    if (system_param.network_provisioned)
                    {
                        // 更新系统状态
                        gwin_main_sys_state_update();
                        gwin_main_sys_state_update_transient(SYS_STATE_NETWORK_PROVISIONED);

                        if (system_param.spec.upload_total)                              // 没有上报过，系统参数强制全部上报一次
                        {
                            system_param.system_upload_force_wait = FORCE_UPLOAD_TIME_NETWORK;      // 配网成功后，延时参数全量上报，防止在选择界面，上报影响SDK原有的逻辑
                        }

                        // 配网成功后锁定model、pid
                        if (!system_param.product.lock)
                        {
                            system_param.product.lock = 1;
                            gwin_custom_record_save(RECORD_ID_PRODUCT_CFG);
                        }
                    }
                    else
                    {
                        // 重置配网，清除所有参数
                        gwin_custom_record_reset_all();
                    }
                }
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_GATT:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {

            }
            else
            {
                uint8_t cfg_value = msg->cfg_value;
                uint8_t gatt_state = cfg_value ? 1 : 0;
                if (system_param.gatt_state != gatt_state)                                  // 没有蓝牙直连到有蓝牙直连，系统参数强制全部上报一次
                {
                    system_param.gatt_state = gatt_state;
                    if (gatt_state)
                    {
                        gwin_main_hold_wakeup(0);
                    }

                    // 更新系统状态
                    gwin_main_sys_state_update();
                }
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_OTA_STATE:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {

            }
            else
            {
                uint8_t cfg_value = msg->cfg_value;
                system_param.ota_state = cfg_value ? 1 : 0;
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_MAC_ADDR:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                uint32_t cfg_value = msg->cfg_value;
                uint8_t *mac_addr = (uint8_t *)cfg_value;
                memcpy(mac_addr, system_param.mac_addr, BLE_MAC_ADDR_LEN);
            }
            else
            {

            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_NETWORK_TIMEOUT:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                uint32_t *value_addr = (uint32_t *)msg->cfg_value;
                *value_addr = system_param.product.network_timeout;
            }
            else
            {
                uint32_t cfg_value = msg->cfg_value;
                if (system_param.product.network_timeout != cfg_value)
                {
                    system_param.product.network_timeout = cfg_value;
                    gwin_custom_record_save(RECORD_ID_PRODUCT_CFG);
                }
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_MODEL_PID:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                uint32_t cfg_value = msg->cfg_value;
                system_param_product_t *product = (system_param_product_t *)cfg_value;
                if (product != NULL)
                {
                    memcpy(product, &system_param.product, sizeof(system_param_product_t));
                }
            }
            else
            {
                uint32_t cfg_value = msg->cfg_value;
                system_param_product_t *product = (system_param_product_t *)cfg_value;
                if (product != NULL)
                {
                    memcpy(&system_param.product, product, sizeof(system_param_product_t));
                    gwin_custom_record_save(RECORD_ID_PRODUCT_CFG);
                }
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_SPEC_SECURITY:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {

            }else
            {
                #if GWIN_MIOT_SECURITY_ENABLE
                uint16_t cfg_value = msg->cfg_value;

                system_param.spec.data[SPEC_INDEX_MIOT_SECURITY_0].change = 1;
                system_param.spec.data[SPEC_INDEX_MIOT_SECURITY_0].siid = cfg_value;
                system_param.spec.data[SPEC_INDEX_MIOT_SECURITY_1].change = 1;
                system_param.spec.data[SPEC_INDEX_MIOT_SECURITY_1].siid = cfg_value;
                gwin_custom_record_save(RECORD_ID_SPEC);

                gwin_save_general_clock(&system_param.system_upload_clock[0]);
                gwin_save_general_clock(&system_param.system_upload_clock[1]);
                #else
                uint16_t cfg_value = msg->cfg_value;

                system_param.spec.data[SPEC_INDEX_MIOT_SECURITY_0].change = 1;
                system_param.spec.data[SPEC_INDEX_MIOT_SECURITY_0].siid = cfg_value;
                gwin_custom_record_save(RECORD_ID_SPEC);

                gwin_save_general_clock(&system_param.system_upload_clock[0]);
                #endif
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_SPEC:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {
                gwin_spec_unit_t *spec_cfg = (gwin_spec_unit_t *)msg->cfg_value;
                int8_t find = -1;
                for (uint8_t i = 0; i < system_param.spec.len; i++)
                {
                    if (spec_cfg->siid == system_param.spec.data[i].siid && spec_cfg->piid == system_param.spec.data[i].piid)
                    {
                        find = i;
                        break;
                    }
                }
                if (find >= 0)
                {
                    uint8_t _find = find;
                    gwin_spec_unit_t *spec = &system_param.spec.data[_find];
                    spec_cfg->len = spec->len;
                    spec_cfg->data_type = spec->data_type;
                    spec_cfg->value = spec->value;
                }
                else
                {
                    spec_cfg->data_type = DATA_TYPE_NONE;
                }
            }
            else
            {
                gwin_spec_unit_t *spec_cfg = (gwin_spec_unit_t *)msg->cfg_value;
                spec_cfg->len = MIN(spec_cfg->len, GWIN_SPEC_STR_UNIT_LEN_MAX);

                // 调试参数表格，打开下面注释
//                if (spec_cfg->data_type == DATA_TYPE_F32)
//                {
//                    float value_f = 0;
//                    memcpy(&value_f, &spec_cfg->value, sizeof(value_f));
//                    USER_DEBUG("siid = %d, piid = %d, data_type = 0x%02x, value = %f", spec_cfg->siid, spec_cfg->piid, spec_cfg->data_type, value_f);
//                }
//                else if (spec_cfg->data_type == DATA_TYPE_STRING)
//                {
//                    USER_DEBUG("siid = %d, piid = %d, data_type = 0x%02x, value_str = %s", spec_cfg->siid, spec_cfg->piid, spec_cfg->data_type, spec_cfg->value);
//                }
//                else
//                {
//                    USER_DEBUG("siid = %d, piid = %d, data_type = 0x%02x, value = %d", spec_cfg->siid, spec_cfg->piid, spec_cfg->data_type, spec_cfg->value);
//                }

                int8_t find = -1;
                for (uint8_t i = 0; i < system_param.spec.len; i++)
                {
                    if (spec_cfg->siid == system_param.spec.data[i].siid && spec_cfg->piid == system_param.spec.data[i].piid)
                    {
                        find = i;
                        break;
                    }
                }
                if (find >= 0)
                {
                    uint8_t _find = find;
                    gwin_spec_unit_t *spec = &system_param.spec.data[_find];

                    // 如果修改了类型，从字符串修改到数字，释放字符串存储
                    if (spec_cfg->data_type != DATA_TYPE_STRING && spec->data_type == DATA_TYPE_STRING)
                    {
                        if (system_param.spec_str.total_cnt > 0 && spec->len > 0)
                        {
                            for (uint8_t j = 0; j < system_param.spec_str.total_cnt; j++)
                            {
                                if (system_param.spec_str.str[j].used
                                        && spec->len == system_param.spec_str.str[j].len
                                        && spec->value == (uint32_t)system_param.spec_str.str[j].data)
                                {
                                    memset(&system_param.spec_str.str[j], 0x00, sizeof(gwin_spec_str_unit_t));
                                    system_param.spec_str.total_cnt--;
                                    system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                                    break;
                                }
                            }
                        }
                    }
                    // 如果修改了类型，从数字修改到字符串，分配字符串存储；如果类型没有修改，都是字符串，但是上次分配字符串存储失败，尝试再次分配
                    else if ((spec_cfg->data_type == DATA_TYPE_STRING && spec->data_type != DATA_TYPE_STRING)
                                || (spec_cfg->data_type == DATA_TYPE_STRING && spec->data_type == DATA_TYPE_STRING && spec->value == (uint32_t)NULL && spec->len == 0))
                    {
                        spec->value = (uint32_t)NULL;
                        if (system_param.spec_str.total_cnt < GWIN_SPEC_STR_LEN_MAX && spec_cfg->len > 0)
                        {
                            for (uint8_t j = 0; j < GWIN_SPEC_STR_LEN_MAX; j++)
                            {
                                if (!system_param.spec_str.str[j].used && system_param.spec_str.str[j].len == 0)
                                {
                                    system_param.spec_str.str[j].used = 1;
                                    system_param.spec_str.total_cnt++;
                                    system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                                    spec->value = (uint32_t)system_param.spec_str.str[j].data;
                                    break;
                                }
                            }
                        }
                    }

                    // 存储数据
                    spec->change = spec_cfg->change;
                    spec->data_type = spec_cfg->data_type;
                    if (spec->data_type == DATA_TYPE_STRING)
                    {
                        if (spec->value != (uint32_t)NULL)
                        {
                            spec->len = spec_cfg->len;
                            gwin_spec_str_unit_t *spec_str_unit = (gwin_spec_str_unit_t *)spec->value;
                            if (spec_str_unit->used)
                            {
                                spec_str_unit->len = spec->len;
                                memset(spec_str_unit->data, 0x00, sizeof(spec_str_unit->data));
                                memcpy(spec_str_unit->data, (const char *)spec_cfg->value, spec_str_unit->len);
                                system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                            }
                        }
                    }
                    else
                    {
                        spec->len = 0;
                        spec->value = spec_cfg->value;
                    }

                    gwin_save_general_clock(&system_param.system_upload_clock[_find]);
                }
                else
                {
                    // 不存在，则新建
                    if (system_param.spec.len == GWIN_SPEC_LEN_MAX)
                    {
                        // 满丢弃最早记录的数据
                        // 如果类型是字符串，先释放字符串存储
                        if (system_param.spec.data[0].data_type == DATA_TYPE_STRING)
                        {
                            if (system_param.spec_str.total_cnt > 0 && system_param.spec.data[0].len > 0)
                            {
                                for (uint8_t j = 0; j < system_param.spec_str.total_cnt; j++)
                                {
                                    if (system_param.spec_str.str[j].used
                                            && system_param.spec.data[0].len == system_param.spec_str.str[j].len
                                            && system_param.spec.data[0].value == (uint32_t)system_param.spec_str.str[j].data)
                                    {
                                        memset(&system_param.spec_str.str[j], 0x00, sizeof(gwin_spec_str_unit_t));
                                        system_param.spec_str.total_cnt--;
                                        system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                                        break;
                                    }
                                }
                            }
                        }
                        // 再丢弃数据
                        memcpy(&system_param.spec.data[0], &system_param.spec.data[1], sizeof(gwin_spec_unit_t) * (GWIN_SPEC_LEN_MAX - 1));
                        system_param.spec.len--;
                    }

                    // 加入到表格里面
                    gwin_spec_unit_t _spec = { 0x00 };
                    gwin_spec_unit_t *spec = &_spec;
                    spec->change = spec_cfg->change;
                    spec->data_type = spec_cfg->data_type;
                    spec->siid = spec_cfg->siid;
                    spec->piid = spec_cfg->piid;
                    if (spec_cfg->data_type == DATA_TYPE_STRING)
                    {
                        // 如果类型是字符串，先增加字符串存储
                        spec->value = (uint32_t)NULL;
                        if (system_param.spec_str.total_cnt < GWIN_SPEC_STR_LEN_MAX && spec_cfg->len > 0)
                        {
                            for (uint8_t j = 0; j < GWIN_SPEC_STR_LEN_MAX; j++)
                            {
                                if (!system_param.spec_str.str[j].used && system_param.spec_str.str[j].len == 0)
                                {
                                    system_param.spec_str.str[j].used = 1;
                                    system_param.spec_str.total_cnt++;
                                    system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                                    spec->value = (uint32_t)system_param.spec_str.str[j].data;
                                    break;
                                }
                            }
                        }

                        // 如果字符串存储满了，要清除旧字符串存储
                        if (spec->value == (uint32_t)NULL)
                        {
                            // 先清除参数表中用到这个字符串存储单元的参数
                            int8_t find = -1;
                            for (uint8_t i = 0; i < system_param.spec.len; i++)
                            {
                                if (system_param.spec.data[i].value == (uint32_t)system_param.spec_str.str[0].data)
                                {
                                    find = i;
                                    break;
                                }
                            }
                            if (find >= 0)
                            {
                                // 丢弃数据
                                if (find == (GWIN_SPEC_LEN_MAX - 1))
                                {
                                    memset(&system_param.spec.data[find], 0x00, sizeof(gwin_spec_unit_t));
                                }
                                else
                                {
                                    memcpy(&system_param.spec.data[find], &system_param.spec.data[find + 1], sizeof(gwin_spec_unit_t) * (GWIN_SPEC_LEN_MAX - 1 - find));
                                }
                                system_param.spec.len--;
                            }
                            // 字符串存储释放旧的单元
                            memset(&system_param.spec_str.str[0], 0x00, sizeof(gwin_spec_str_unit_t));
                            system_param.spec_str.total_cnt--;
                            system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                            // 字符串存储用旧的单元重新分配
                            system_param.spec_str.str[0].used = 1;
                            system_param.spec_str.total_cnt++;
                            system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                            spec->value = (uint32_t)system_param.spec_str.str[0].data;
                        }

                        gwin_spec_str_unit_t *spec_str_unit = (gwin_spec_str_unit_t*) spec->value;
                        if (spec_str_unit->used)
                        {
                            spec->len = spec_cfg->len;
                            spec_str_unit->len = spec_cfg->len;
                            memset(spec_str_unit->data, 0x00, sizeof(spec_str_unit->data));
                            memcpy(spec_str_unit->data, (const char *)spec_cfg->value, spec_str_unit->len);
                            system_param.delay_spec_str_save = DELAY_SPEC_SAVE;
                        }
                    }
                    else
                    {
                        spec->len = 0;
                        spec->value = spec_cfg->value;
                    }
                    system_param.spec.data[system_param.spec.len] = _spec;

                    gwin_save_general_clock(&system_param.system_upload_clock[system_param.spec.len]);
                    system_param.spec.len++;
                }

                // 调试参数表格，打开下面注释
//                USER_DEBUG("str map: %d", system_param.spec_str.total_cnt);
//                for (uint8_t i = 0; i < GWIN_SPEC_STR_LEN_MAX; i++)
//                {
//                    USER_DEBUG("[%d]: used = %d, len = %d, str = %x %s", i, system_param.spec_str.str[i].used, system_param.spec_str.str[i].len, system_param.spec_str.str[i].data, system_param.spec_str.str[i].data);
//                }
//
//                USER_DEBUG("spec map:");
//                for (uint8_t i = 0; i < system_param.spec.len; i++)
//                {
//                    float value_f = 0;
//                    const char *value_str = NULL;
//
//                    if (system_param.spec.data[i].data_type == DATA_TYPE_F32)
//                    {
//                        memcpy(&value_f, &system_param.spec.data[i].value, sizeof(value_f));
//                        USER_DEBUG("[%d]: %d %d : change = %d, data_type = 0x%02x, value = %f", i, system_param.spec.data[i].siid, system_param.spec.data[i].piid, system_param.spec.data[i].change, system_param.spec.data[i].data_type, value_f);
//                    }
//                    else if (system_param.spec.data[i].data_type == DATA_TYPE_STRING)
//                    {
//                        value_str = (const char *)system_param.spec.data[i].value;
//                        USER_DEBUG("[%d]: %d %d : change = %d, data_type = 0x%02x, value_str = %x %s", i, system_param.spec.data[i].siid, system_param.spec.data[i].piid, system_param.spec.data[i].change, system_param.spec.data[i].data_type, value_str, value_str);
//                    }
//                    else
//                    {
//                        USER_DEBUG("[%d]: %d %d : change = %d, data_type = 0x%02x, value = %d", i, system_param.spec.data[i].siid, system_param.spec.data[i].piid, system_param.spec.data[i].change, system_param.spec.data[i].data_type, system_param.spec.data[i].value);
//                    }
//                }
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_SPEC_SAVE:
            if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET)
            {

            }
            else
            {
                system_param.delay_spec_save = DELAY_SPEC_SAVE;
                // LIN MARK 20240402 : MHCWB11S SDK，串口接收有bug，注意频繁写flash，会频繁关闭中断，导出串口rx偏移
                // gwin_custom_record_save(RECORD_ID_SPEC);
            }
            break;

        case MAIN_TASK_MSG_CFG_SUBTYPE_SET_INFO_PKT:
            {
                GWIN_DEBUG("gwin ble adv set info pkt");
                gwin_dynamic_qr_code_init();
                gwin_dynamic_qr_code_set();

                // 启动定时器
                _os_timer_start(adv_dev_info_pkt, 0);
            }
            break;

        default:
            GWIN_DEBUG("Error : subtype of cfg msg is unknown %d !!!", subtype);
            break;
    }

    if (action_type == MAIN_TASK_MSG_CFG_ACT_TYPE_GET
            && subtype != MAIN_TASK_MSG_CFG_SUBTYPE_MODEL_PID)
    {
        GWIN_DEBUG("cfg get value = %d", *(uint32_t *)msg->cfg_value);
    }
}

/**
 * @brief 外部动作消息处理
 */
static void gwin_main_task_extern_action_msg_handle(gwin_main_task_msg_t *msg)
{
    // 某些条件不响应外部指令
    if (system_param.reboot)
    {
        GWIN_DEBUG("reboot!!!");
        return;
    }
    if (system_param.network_reset)
    {
        GWIN_DEBUG("network reset!!!");
        return;
    }
    if (system_param.factory_test)
    {
        GWIN_DEBUG("factory test!!!");
        return;
    }
    if (system_param.ota_state)
    {
        GWIN_DEBUG("ota is running!!!");
        return;
    }

    uint16_t subtype = msg->subtype;
    if (subtype != MAIN_TASK_MSG_EX_ACT_SUBTYPE_WAKEUP)
    {
        GWIN_DEBUG("subtype = %d", subtype);
    }

    switch(subtype)
    {
        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_WAKEUP:
            {
                uint8_t low_pwr = gwin_low_pwr_check();

                gwin_main_hold_wakeup(0);

                uint8_t pin = msg->param;
                GWIN_DEBUG("wakeup pin = %d", pin);

                if (low_pwr && pin != 0)
                {
                    // 更新系统状态
                    gwin_main_sys_state_update();
                }
            }
            break;

        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_FUNC_START:
            gwin_main_func_start();
            break;

        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_LOW_PWR:
            break;

        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_ACTIVE_PAIR:
            if (!system_param.gatt_state && !system_param.network_provisioned)
            {
                uint8_t active_pair_time = msg->ext_param;
                active_pair_time = MAX(active_pair_time, 1);
                system_param.active_pair_time = active_pair_time;
                miio_ble_user_adv_init(1);
                gwin_main_ble_set_adv_interval(1, 1);
                miio_ble_set_adv_timeout(system_param.product.network_timeout);
            }
            break;

        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_NET_RESET:
            gwin_main_network_reset();
            break;

        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_FACTORY_TEST:
            gwin_main_factory_test();
            break;

            // 强制复位所有参数（研发预留接口，防止错误，直接响应）
        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_RESET_ALL_FORCE:
            gwin_main_reset_all_force_callback(NULL);
            break;

        case MAIN_TASK_MSG_EX_ACT_SUBTYPE_SET_PAIR_MODE:
            {
                // 00 默认扫码配网, 01 按键配网
                uint8_t pair_qr_mode = (msg->ext_param == 0x00 ? 1 : 0);
                gwin_set_m_config_io_oob_qr_code_out(pair_qr_mode);
            }
            break;

        default:
            GWIN_DEBUG("Error : subtype of ex act msg is unknown %d !!!", subtype);
            break;
    }
}



/**
 * @brief 任务初始化
 */
void gwin_main_task_init(void)
{
    _os_timer_create(reset_all_force, 5000, FALSE, 0, gwin_main_reset_all_force_callback);
    GWIN_OS_TIMER_ASSERT(_os_timer_handle(reset_all_force));
    _os_timer_create(one_second, 1000, TRUE, 0, gwin_main_one_second_callback);
    GWIN_OS_TIMER_ASSERT(_os_timer_handle(one_second));
    _os_timer_create(pwr_on_wait_loop, 500, FALSE, 0, gwin_main_pwr_on_wait_loop_callback);
    GWIN_OS_TIMER_ASSERT(_os_timer_handle(pwr_on_wait_loop));
    _os_timer_create(low_pwr_enter, 500, FALSE, 0, gwin_main_low_pwr_enter_callback);
    GWIN_OS_TIMER_ASSERT(_os_timer_handle(low_pwr_enter));

    _os_timer_create(adv_dev_info_pkt, 1000, FALSE, 0, gwin_main_adv_dev_info_pkt_callback);
    GWIN_OS_TIMER_ASSERT(_os_timer_handle(adv_dev_info_pkt));

    os_msg_queue_create(&gwin_main_queue_handle, GWIN_MAIN_TASK_QUEUE_MAX_NUM, sizeof(gwin_main_task_msg_t));

    os_task_create(&gwin_main_task_handle, "gwin_main_task", gwin_main_task, NULL, GWIN_MAIN_TASK_STACK_SIZE, GWIN_MAIN_TASK_PRIORITY);

    if (system_param.reset_all_force)
    {
        _os_timer_start(reset_all_force, 0);
    }
}

/**
 * @brief 发送消息
 */
uint8_t gwin_send_msg_to_main_task(gwin_main_task_msg_t *p_msg)
{
    os_msg_send(gwin_main_queue_handle, p_msg, 0);
    return 1;
}


/**
 * @brief 定时器 检查产品标识符
 */
static void gwin_main_reset_all_force_callback(void *arg)
{
    _os_timer_clear(reset_all_force);

    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_TIMER;
    msg.subtype = MAIN_TASK_MSG_TIMER_SUBTYPE_RESET_ALL_FORCE;
    gwin_send_msg_to_main_task(&msg);
}

/**
 * @brief 定时器 任务活跃
 */
static void gwin_main_one_second_callback(void *arg)
{
    _os_timer_clear(one_second);

    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_TIMER;
    msg.subtype = MAIN_TASK_MSG_TIMER_SUBTYPE_ONE_SECOND;
    gwin_send_msg_to_main_task(&msg);
}

/**
 * @brief 定时器 上电等待授权参数
 */
static void gwin_main_pwr_on_wait_loop_callback(void *arg)
{
    _os_timer_clear(pwr_on_wait_loop);

    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_TIMER;
    msg.subtype = MAIN_TASK_MSG_TIMER_SUBTYPE_PWR_ON_WAIT_LOOP;
    gwin_send_msg_to_main_task(&msg);
}

/**
 * @brief 定时器 等待串口发送数据再进低功耗
 */
static void gwin_main_low_pwr_enter_callback(void *arg)
{
    _os_timer_clear(low_pwr_enter);

    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_TIMER;
    msg.subtype = MAIN_TASK_MSG_TIMER_SUBTYPE_LOW_PWR_ENTER;
    gwin_send_msg_to_main_task(&msg);
}

static void gwin_main_adv_dev_info_pkt_callback(void *arg)
{
    _os_timer_clear(adv_dev_info_pkt);

    gwin_main_task_msg_t msg = { 0 };
    msg.type = MAIN_TASK_MSG_TYPE_TIMER;
    msg.subtype = MAIN_TASK_MSG_TIMER_SUBTYPE_STOP_INFO_PKT;
    gwin_send_msg_to_main_task(&msg); 
}


/**
 * @brief 任务
 */
static void gwin_main_task(void *arg)
{
    gwin_main_task_msg_t msg;

    gwin_main_power_on();

    while (1)
    {
        if (os_msg_recv(gwin_main_queue_handle, &msg, 0xFFFFFFFF) == true)
        {
            switch(msg.type)
            {
                case MAIN_TASK_MSG_TYPE_TIMER:
                    gwin_main_task_timer_msg_handle(&msg);
                    break;

                case MAIN_TASK_MSG_TYPE_CFG:
                    gwin_main_task_cfg_msg_handle(&msg);
                    break;

                case MAIN_TASK_MSG_TYPE_EX_ACT:
                    gwin_main_task_extern_action_msg_handle(&msg);
                    break;

                default:
                    break;
            }
        }
    }
}


/*-------------------------- END OF FILE ------------------------------------*/

